﻿/*
 * Created by SharpDevelop.
 * User: phtrung
 * Date: 8/4/2009
 * Time: 5:04 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;



namespace popLib
{
	/// <summary>
	/// Description of WindowLib.
	/// </summary>
	public class WindowLib
	{
		
		#region Process functions
		/// <summary>
		/// Kill the process with name in the pass list.
		/// </summary>
		/// <param name="processNames">Array string name of each process</param>
		public static void killProcess( string[] processNames ){
			foreach( string process in processNames )
				killProcess(process);
		}
		
		/// <summary>
		/// Kill all processes that have same name.
		/// </summary>
		/// <param name="processName"></param>
		public static void killProcess(string processName){
			Process[] processlist = Process.GetProcessesByName(processName);
			foreach(Process theprocess in processlist){				
				theprocess.Kill();
				theprocess.Close();					
				theprocess.Dispose();				
			}
		}
		
		/// <summary>
		/// Kill all processes that have same name.
		/// </summary>
		/// <param name="processName"></param>
		public static void killProcessById(int processID){
			try{
				Process process = Process.GetProcessById(processID);			
				if( process != null ){
					process.Kill();
					process.Close();					
					process.Dispose();
				}
			}catch(Exception ex){ex.ToString();}
		}
		
		/// <summary>
		/// Check is the process with that name is existed or not
		/// </summary>
		/// <param name="_processName"></param>
		/// <returns></returns>
		public static bool isProcessExist(string processName){
			if( Process.GetProcessesByName(processName).Length > 0 ) return true;
			return false;			
		}
		
		/// <summary>
		/// Check is the process with that ID is existed or not
		/// </summary>
		/// <param name="_processName"></param>
		/// <returns></returns>
		public static bool isProcessIDExist(int processID){
			try{
				if( Process.GetProcessById(processID) != null ) return true;
			}catch(Exception ex){ex.ToString();}
			return false;			
		}
		
		/// <summary>
		/// Check is the process with that name is existed or not
		/// </summary>
		/// <param name="_processName"></param>
		/// <returns></returns>
		public static int getProcessCount(string _processName){
			return Process.GetProcessesByName(_processName).Length;
		}
		#endregion

        public static void startApplication(string file, string arg = null, bool waitForExit = false, int milisecondToWait = 0 )
        {
			try{
				ProcessStartInfo info = new ProcessStartInfo();
				info.FileName = file;
				if( StringLib.isValid(arg) ) info.Arguments = arg;
				info.WorkingDirectory = Path.GetDirectoryName(file);                
				Process pro = Process.Start( info );
                if (waitForExit && milisecondToWait == 0) pro.WaitForExit();
                if (waitForExit && milisecondToWait > 0) pro.WaitForExit(milisecondToWait);

			}catch{}
		}		
				
		public static void handleTaskbar( bool isVisible ){
			IntPtr handle = APILib.FindWindow( "Shell_TrayWnd", "" );
			APILib.ShowWindow( handle, isVisible ? 1 : 0 );
		}
		
		
		
		public static void controlWindow(ExitWindowsExFlag flag){
			switch( flag ){
				case ExitWindowsExFlag.LogOff:
				case ExitWindowsExFlag.Restart:
				case ExitWindowsExFlag.Shutdown:
				case ExitWindowsExFlag.LogOffForce: 
					APILib.ExitWindowsEx( (int)flag , 0);
					break;
				case ExitWindowsExFlag.Hibernate:
					Application.SetSuspendState(PowerState.Hibernate, true, true);
					break;
				case ExitWindowsExFlag.Standby:
					Application.SetSuspendState(PowerState.Suspend, true, true);
					break;
			}
		}
		
		
		
		public static void resgistryControl(RegCommand command, bool isLock){
			string path = "";
			string key  = command.ToString();
			
			switch( command ){
				case RegCommand.DisableCMD: path = @"Software\Policies\Microsoft\Windows\System\"; break;
				case RegCommand.NoControlPanel: path = @"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\"; break;
				case RegCommand.USBWriteProtect: 
					path = @"SYSTEM\CurrentControlSet\Control\StorageDevicePolicies\"; 
					key = "WriteProtect";
					break;
				
				default : path = @"Software\Microsoft\Windows\CurrentVersion\Policies\System\"; break;
				
			}
			
			setRegistryValue( RegistryRoot.CurrentUser, path, key, isLock ? 1 : 0 );
		}
		
		
		
		public static void setRegistryValue( RegistryRoot root, string path, string key, int value){
			RegistryKey regRoot = Registry.ClassesRoot;			
			switch( root ){
				case RegistryRoot.CurrentConfig: regRoot = Registry.CurrentConfig; break;
				case RegistryRoot.CurrentUser: regRoot 	 = Registry.CurrentUser; break;
				case RegistryRoot.LocalMachine: regRoot  = Registry.LocalMachine; break;
				case RegistryRoot.ClassesRoot: regRoot 	 = Registry.ClassesRoot; break;
			}
			
			RegistryKey regKey = regRoot.OpenSubKey( path, true );
			if( regKey == null ) regKey = regRoot.CreateSubKey( path );
			try{
				regKey.SetValue( key, value, RegistryValueKind.DWord );
			}finally{
				regKey.Close();
			}
		}
		
		public static void setRegistryValue( RegistryRoot root, string path, string key, object value, RegistryValueKind valueKind){
			RegistryKey regRoot = Registry.ClassesRoot;			
			switch( root ){
				case RegistryRoot.CurrentConfig: regRoot = Registry.CurrentConfig; break;
				case RegistryRoot.CurrentUser: regRoot 	 = Registry.CurrentUser; break;
				case RegistryRoot.LocalMachine: regRoot  = Registry.LocalMachine; break;
				case RegistryRoot.ClassesRoot: regRoot 	 = Registry.ClassesRoot; break;
			}
			
			RegistryKey regKey = regRoot.OpenSubKey( path, true );
			if( regKey == null ) regKey = regRoot.CreateSubKey( path );
			try{
				regKey.SetValue( key, value, valueKind );
			}finally{
				regKey.Close();
			}
		}
		
		
		
		public static Process[] getProcessesByPath(string path)
        {
            string processname = Path.GetFileNameWithoutExtension(path);
            Process[] processes = Process.GetProcessesByName(processname);
            List<Process> result = new List<Process>();
            foreach (Process pro in processes)
            {
            	try{
	            	if (path.ToLower().Trim() == pro.MainModule.FileName.ToLower().Trim())
	            		result.Add( pro );
            	}catch{}
            }
            return result.ToArray();
        }
		
		public static string[] getCommandPromptOutput(string exeFile, string arguments, int secondTimeOut){
			Process netUtility = new Process(); 
			netUtility.StartInfo.FileName = exeFile; 
			netUtility.StartInfo.CreateNoWindow = true; 
			if(StringLib.isValid(arguments)) 
				netUtility.StartInfo.Arguments = arguments;
			netUtility.StartInfo.RedirectStandardOutput = true; 
			netUtility.StartInfo.UseShellExecute = false; 
			netUtility.StartInfo.RedirectStandardError = true; 
			netUtility.Start(); 
			
			StreamReader streamReader = new StreamReader(netUtility.StandardOutput.BaseStream, netUtility.StandardOutput.CurrentEncoding); 
			
			string line = "";
			List<string> tmp = new List<string>();			
			while ((line = streamReader.ReadLine()) != null) 
				if( StringLib.isValid(line) ) tmp.Add(line);
			
			
			streamReader.Close(); 
			netUtility.WaitForExit(secondTimeOut*1000);
			return tmp.ToArray();
		}
		
		public static string getCommandPromptOutputString(string exeFile, string arguments, int secondTimeOut){
			Process netUtility = new Process(); 
			netUtility.StartInfo.FileName = exeFile; 
			netUtility.StartInfo.CreateNoWindow = true; 
			if(StringLib.isValid(arguments)) 
				netUtility.StartInfo.Arguments = arguments;
			netUtility.StartInfo.RedirectStandardOutput = true; 
			netUtility.StartInfo.UseShellExecute = false; 
			netUtility.StartInfo.RedirectStandardError = true; 
			netUtility.Start(); 
			
			StreamReader streamReader = new StreamReader(netUtility.StandardOutput.BaseStream, netUtility.StandardOutput.CurrentEncoding); 
			string result = streamReader.ReadToEnd();
			
			streamReader.Close(); 
			netUtility.WaitForExit(secondTimeOut*1000);
			return result;
		}
		/*
		public static string[] getStartupApplication(){
			List<string> startupFiles = new List<string>();
			
			string path = @"Software\Microsoft\Windows\CurrentVersion\Run";
			RegistryKey regKey = Registry.CurrentUser.OpenSubKey( path, true );
			
			foreach( string valueName in regKey.GetValueNames() ){
				startupFiles.Add( regKey.GetValue(valueName).ToString() );
			}
			
			regKey = Registry.LocalMachine.OpenSubKey( path, true );
			foreach( string valueName in regKey.GetValueNames() ){
				startupFiles.Add( regKey.GetValue(valueName).ToString() );
			}
			
			IWshShortcut link;
			WshShell shell = new WshShellClass();
			string startup = Environment.GetFolderPath( Environment.SpecialFolder.Startup );
			string[] files = Directory.GetFiles( startup, "*.lnk" );
			foreach( string file in files ){				
				link = (IWshShortcut)shell.CreateShortcut(file);
				startupFiles.Add( link.TargetPath );
			}
			
			return startupFiles.ToArray();
		}
		*/
		
		public static void PressKeyGroup( Keys[] keys ){
			foreach( Keys key in keys )
				PressKey(key,true);
			foreach( Keys key in keys )
				PressKey(key,false);
		}
		
		public static void PressKey( Keys key ){			
			PressKey(key,true);
			PressKey(key,false);
		}		
		
		public static void PressKey( Keys key, bool isKeyDown ){
			if( key.ToString().Length == 1 )
				APILib.keybd_event( (byte)key, 0, isKeyDown ? APILib.KEYEVENTF_KEYDOWN : APILib.KEYEVENTF_KEYUP, 0 );
			else{				
				APILib.keybd_event( (byte)((APILib.VK)Enum.Parse(typeof(APILib.VK),key.ToString().ToUpper())),
				                   0, isKeyDown ? APILib.KEYEVENTF_KEYDOWN : APILib.KEYEVENTF_KEYUP, 0 );
			}
		}
		
		public static void MouseClick( MouseButtons button, int x, int y ){
			Cursor.Position = new Point(x,y);
			
			int flag = 0;
			switch(button){
				case MouseButtons.Left: flag = (int)APILib.MouseEventFlags.LEFTDOWN | (int)APILib.MouseEventFlags.LEFTUP; break;
				case MouseButtons.Right: flag = (int)APILib.MouseEventFlags.RIGHTDOWN | (int)APILib.MouseEventFlags.RIGHTUP; break;
				case MouseButtons.Middle: flag = (int)APILib.MouseEventFlags.MIDDLEDOWN | (int)APILib.MouseEventFlags.MIDDLEUP; break;
			}
			APILib.mouse_event( flag, 0, 0, 0, 0);
		}
		
		public static void MouseClick( MouseButtons button, int x, int y, bool isUp ){
			Cursor.Position = new Point(x,y);
			
			int flag = 0;
			if( isUp ){
				switch(button){
					case MouseButtons.Left: flag = (int)APILib.MouseEventFlags.LEFTUP; break;
					case MouseButtons.Right: flag = (int)APILib.MouseEventFlags.RIGHTUP; break;
					case MouseButtons.Middle: flag = (int)APILib.MouseEventFlags.MIDDLEUP; break;
				}
			}else{
				switch(button){
					case MouseButtons.Left: flag = (int)APILib.MouseEventFlags.LEFTDOWN; break;
					case MouseButtons.Right: flag = (int)APILib.MouseEventFlags.RIGHTDOWN; break;
					case MouseButtons.Middle: flag = (int)APILib.MouseEventFlags.MIDDLEDOWN; break;
				}
			}
			
			APILib.mouse_event( flag, 0, 0, 0, 0);
			
		}


        
        public static List<IntPtr> GetChildWindows(IntPtr parent)
        {
            List<IntPtr> result = new List<IntPtr>();
            GCHandle listHandle = GCHandle.Alloc(result);
            try
            {
                APILib.EnumWindowsProc childProc = new APILib.EnumWindowsProc(EnumWindow);
                APILib.EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
            }
            finally
            {
                if (listHandle.IsAllocated)
                    listHandle.Free();
            }
            return result;
        }

        public static bool EnumWindow(IntPtr handle, IntPtr pointer)
        {
            GCHandle gch = GCHandle.FromIntPtr(pointer);
            List<IntPtr> list = gch.Target as List<IntPtr>;
            if (list == null)
            {
                throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
            }
            list.Add(handle);
            //  You can modify this to check to see if you want to cancel the operation, then return a null here
            return true;
        }

        public static string GetWindowTitle(IntPtr windowHandle)
        {
            StringBuilder sb = new StringBuilder(APILib.GetWindowTextLength(windowHandle) + 1);
            APILib.GetWindowText(windowHandle, sb, sb.Capacity);
            return sb.ToString();
        }

        public static void SetWindowTitle(IntPtr windowHandle, string title)
        {
            UInt32 WM_SETTEXT = 0x000c;
            APILib.SendMessageW(windowHandle, WM_SETTEXT, IntPtr.Zero, title);
        }

        public static Rectangle GetWindowRectangle(IntPtr windowHandle)
        {
            Rectangle myRect = new Rectangle();
            RECT rct;

            APILib.GetWindowRect(new HandleRef(null, windowHandle), out rct);

            myRect.X = rct.Left;
            myRect.Y = rct.Top;
            myRect.Width = rct.Right - rct.Left + 1;
            myRect.Height = rct.Bottom - rct.Top + 1;

            return myRect;
        }

        public static void SetWindowPos(IntPtr windowHandle, SpecialWindowHandlesFlags flag, int x, int y, int width, int height, SetWindowPosFlags pos)
        {
            APILib.SetWindowPos(windowHandle, (IntPtr)flag, x, y, width, height, pos);
        }

        public static Icon GetWindowIcon(IntPtr handle)
        {
            int result;

            APILib.SendMessageTimeout(handle, (int)SendMessageCode.WM_GETICON, (int)SendMessageCode.ICON_SMALL, 0,
              (int)SendMessageCode.SMTO_ABORTIFHUNG, 1000, out result);

            IntPtr IconHandle = new IntPtr(result);

            if (IconHandle == IntPtr.Zero)
            {
                result = APILib.GetClassLong(handle, (int)SendMessageCode.GCL_HICONSM);
                IconHandle = new IntPtr(result);
            }

            if (IconHandle == IntPtr.Zero)
            {
                APILib.SendMessageTimeout(handle, (int)SendMessageCode.WM_QUERYDRAGICON, 0, 0,
                    (int)SendMessageCode.SMTO_ABORTIFHUNG, 1000, out result);
                IconHandle = new IntPtr(result);
            }

            if (IconHandle == IntPtr.Zero)
            {
                return null;
            }

            System.Drawing.Icon temp = System.Drawing.Icon.FromHandle(IconHandle);
            System.Drawing.Icon icon = (System.Drawing.Icon)temp.Clone();

            APILib.DestroyIcon(IconHandle);

            return icon;
        }

        public static Icon GetExecutableIcon(IntPtr handle)
        {
            System.Drawing.Icon icon = null;
            string path = GetExecutablePath(handle);
            if (System.IO.File.Exists(path))
            {
                SHFILEINFO info = new SHFILEINFO();
                APILib.SHGetFileInfo(path, 0, ref info, (uint)Marshal.SizeOf(info), (int)SendMessageCode.SHGFI_ICON | (int)SendMessageCode.SHGFI_SMALLICON);

                System.Drawing.Icon temp = System.Drawing.Icon.FromHandle(info.hIcon);
                icon = (System.Drawing.Icon)temp.Clone();
                APILib.DestroyIcon(temp.Handle);
            }

            return icon;
        }

        public static string GetExecutablePath(IntPtr handle)
        {
            uint dwProcessId;
            APILib.GetWindowThreadProcessId(handle, out dwProcessId);
            IntPtr hProcess = APILib.OpenProcess(ProcessAccessFlags.VMRead | ProcessAccessFlags.QueryInformation, false, dwProcessId);
            StringBuilder path = new StringBuilder(1024);
            APILib.GetModuleFileNameEx(hProcess, IntPtr.Zero, path, 1024);
            APILib.CloseHandle(hProcess);
            return path.ToString();
        }

        
	}
	
	public enum RegCommand{
		DisableCMD, DisableChangePassword, DisableLockWorkstation, DisableRegedit, DisableRegistryTools, NoFolderOptions, USBWriteProtect,
		NoControlPanel
	}
	
	public enum ExitWindowsExFlag{
    	LogOff = 0,
    	Restart = 2,
    	Shutdown = 1,
    	LogOffForce = 4,
    	Standby = 5,
    	Hibernate = 6,
    	LockWorkstation = 7
    }
	
	public enum RegistryRoot{
		ClassesRoot, CurrentConfig, CurrentUser, LocalMachine
	}
}
